﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace RCSP.Common.Configurations
{
    /// <summary>
    /// Base configuration class
    /// </summary>
    /// <typeparam name="TConfig"></typeparam>
    public abstract class AppConfigBase<TConfig> : IMappingConfiguration
        where TConfig : AppConfigurationSection
    {
        /// <summary>
        /// Configuration provider secton name
        /// </summary>
        public abstract string ProviderSectionName { get; }

        /// <summary>
        /// Gets configuration section
        /// </summary>
        public TConfig GetConfiguration
        {
            get
            {
                var provider = ConfigurationManager.GetSection(ProviderSectionName);
                if (provider == null)
                    throw new ArgumentException(String.Format("Section {0} not found", ProviderSectionName));

                if (typeof(AppConfigurationProvider<TConfig>).IsAssignableFrom(provider.GetType()))
                    return ((AppConfigurationProvider<TConfig>)provider).Configuration;
                throw new ArgumentException(String.Format("Unexpected type {0} of section {1}", provider.GetType().FullName, ProviderSectionName));
            }
        }

        /// <summary>
        /// Gets mapping for slecified type of entity
        /// </summary>
        public EntityMapping GetEntityMapping<TEntity>()
        {
            var xmlEntityMappingList = GetConfiguration.Mappings;

            var xmlEntityMapping = xmlEntityMappingList.FirstOrDefault(item => Type.GetType(item.EntityType) == typeof(TEntity));
            if (xmlEntityMapping == null)
            {
                StringBuilder sb = new StringBuilder();
                foreach (XmlEntityMappingConfiguration xmlConf in xmlEntityMappingList)
                {
                    sb.AppendLine(xmlConf.TableName);
                }


                throw new ArgumentException(String.Format("Cannot find type '{0}' in mapping configuration + | {1}", typeof(TEntity).FullName, sb.ToString()));
            }
            var propertiesMapping = new Dictionary<string, PropertyMapping>();
            foreach (var propertyMapping in xmlEntityMapping.PropertyMappings)
            {
                propertiesMapping.Add(propertyMapping.PropertyName,
                    new PropertyMapping(System.Web.HttpUtility.UrlDecode(propertyMapping.ColumnName), propertyMapping.ReadOnly));
            }

            if (!string.IsNullOrEmpty(xmlEntityMapping.ConnectionString))
            {
                // && !string.IsNullOrEmpty(xmlEntityMapping.WebName)
                return new EntityMapping(typeof(TEntity), System.Web.HttpUtility.UrlDecode(xmlEntityMapping.TableName), propertiesMapping, xmlEntityMapping.ConnectionString);
            }
            else
            {
                return new EntityMapping(typeof(TEntity), System.Web.HttpUtility.UrlDecode(xmlEntityMapping.TableName), propertiesMapping);
            }

        }

        /// <summary>
        /// Is entity mapping defined
        /// </summary>
        /// <typeparam name="T">Type of entity</typeparam>
        /// <returns>True, if entity mapping defined, otherwise false</returns>
        public bool CheckIsEntityMappingDefined<T>()
        {
            return GetConfiguration.Mappings.Exists(
                item => Type.GetType(item.EntityType) == typeof(T));
        }

    }
}
